package com.qiaoba.auth.aspect;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.qiaoba.api.auth.entity.dto.LoginDTO;
import com.qiaoba.api.auth.service.AuthConfigApiService;
import com.qiaoba.auth.entity.SysLoginLog;
import com.qiaoba.auth.service.SysLoginLogService;
import com.qiaoba.common.base.constant.BaseConstant;
import com.qiaoba.common.base.exception.ServiceException;
import com.qiaoba.web.util.IpUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * 登陆日志 AOP
 *
 * @author ailanyin
 * @date 2023-09-24 10:09:36
 */
@Aspect
@Component
@RequiredArgsConstructor
@Slf4j
public class LoginLogAspect {

    private final SysLoginLogService sysLoginLogService;
    private final AuthConfigApiService authConfigApiService;

    @AfterReturning(pointcut = "execution(* com.qiaoba.auth.controller.SysLoginController.login(..))", returning = "result")
    public void logSuccessfulLogin(JoinPoint joinPoint, Object result) {
        // 记录日志成功开关-关
        if (!authConfigApiService.getLoginSuccessLogConfig()) {
            return;
        }
        // 说明登陆成功
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String ip = IpUtil.getIp(request);
        UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
        ThreadUtil.execAsync(() -> insertLog(ip, userAgent, joinPoint, BaseConstant.SUCCESS, "登陆成功"));
    }

    @AfterThrowing(pointcut = "execution(* com.qiaoba.auth.controller.SysLoginController.login(..))", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
        // 记录日志失败开关-关
        if (!authConfigApiService.getLoginFailLogConfig()) {
            return;
        }
        // 说明登陆失败
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String ip = IpUtil.getIp(request);
        UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent"));
        ThreadUtil.execAsync(() -> insertLog(ip, userAgent, joinPoint, BaseConstant.FAIL, e.getMessage()));
    }

    private void insertLog(String ip, UserAgent userAgent, JoinPoint joinPoint, String status, String msg) {
        String username = getUsername(joinPoint);
        String browser = userAgent.getBrowser().getName() + userAgent.getVersion();
        String os = userAgent.getOs().getName();

        SysLoginLog sysLoginLog = new SysLoginLog();
        sysLoginLog.setUsername(username);
        sysLoginLog.setIp(ip);
        sysLoginLog.setAddress(IpUtil.getIpAddr(ip));
        sysLoginLog.setBrowser(browser);
        sysLoginLog.setOs(os);
        sysLoginLog.setStatus(status);
        sysLoginLog.setMsg(msg);
        sysLoginLog.setLoginTime(new Date());

        sysLoginLogService.insert(sysLoginLog);
    }

    private String getUsername(JoinPoint joinPoint) {
        // 获取方法的参数
        Object[] args = joinPoint.getArgs();
        // 遍历参数并处理
        for (Object arg : args) {
            if (arg instanceof LoginDTO) {
                return ((LoginDTO) arg).getUsername();
            }
        }
        throw new ServiceException("登陆日志AOP登陆账号获取失败！");
    }
}
